package com.syni.mdd.yhd.common.all.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.syni.mdd.sjb.common.component.utils.common.utils.ArithUtil;
import com.syni.mdd.sjb.common.component.utils.common.utils.ParamsMap;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.entity.BmsDxOrder;
import com.syni.mdd.yhd.common.all.entity.order.OrderCommitHolder;
import com.syni.mdd.yhd.common.all.entity.platformGood.BmsPlatformGood;
import com.syni.mdd.yhd.common.all.enums.ActivityEnums;
import com.syni.mdd.yhd.common.all.enums.platformGood.PlatformGoodEnum;
import com.syni.mdd.yhd.common.all.service.BmsDxOrderService;
import com.syni.mdd.yhd.common.all.service.order.OrderCommitService;
import com.syni.mdd.yhd.common.all.service.platformGoods.BmsPlatformGoodService;
import com.syni.mdd.yhd.common.all.utils.*;
import com.syni.mdd.sjb.common.component.utils.redis.utils.RedisTemplateUtils;;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import java.util.HashMap;
import java.util.Map;

/**
 * @className PlatformOrderServiceImpl
 * @description TOO
 * @Author cfx
 * @DATE 2020/3/13 22:34
 * @VERSION 1.0
 **/
@Component
public class PlatformOrderServiceImpl implements OrderCommitService {
    @Autowired
    BmsPlatformGoodService bmsPlatformGoodService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    BmsDxOrderService bmsDxOrderService;

    @Autowired
    EntityManager entityManager;
    @Override
    public OrderCommitHolder commitLogic(OrderCommitHolder orderCommitHolder) {
        ParamsMap paramsMap = orderCommitHolder.getParamsMap();
        String uuid = WebUtils.getUUId();
        Map<String, Object> checkMap = RequestParamUtils.checkParams(orderCommitHolder.getParamsMap(), "goodNum", "goodId", "address", "buyArea");
        if (!(checkMap.containsKey("status") && ResultCode.CODE_NORMAL.equals(checkMap.get("status").toString()))) {
            orderCommitHolder.getExecutionResult().putAll(checkMap);
            return orderCommitHolder;
        }
        Integer goodId = paramsMap.getInteger("goodId");
        //联系人
        String contact = paramsMap.getString("contact");
        //联系电话
        String contactPhone = paramsMap.getString("phone");
        String address = paramsMap.getString("address");
        Integer buyArea = paramsMap.getInteger("buyArea");
        Integer userId = paramsMap.getInteger("userIdentify");
        BmsPlatformGood bmsPlatformGood = bmsPlatformGoodService.findById(goodId);
        BmsDxOrder bmsDxOrder = orderCommitHolder.getBmsDxOrder();
        //购买数量
        Integer num = paramsMap.getInteger("goodNum");
        if (bmsPlatformGood == null) {
            orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_NO_EXIST));
            return orderCommitHolder;
        }
        if (bmsPlatformGood.getIsOff() == Constants.COMMON_FLAG_TRUE_INT) {
            orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_IS_OFF));
            return orderCommitHolder;
        }
        if (bmsPlatformGood.getInventory() <= 0) {
            orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_INV_NO));
            return orderCommitHolder;
        }
        if (bmsPlatformGood.getInventory() < num) {
            orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_INV_NO));
            return orderCommitHolder;
        }
        if (bmsPlatformGood.getIsLimitBuyDay() == Constants.COMMON_FLAG_TRUE_INT) {
            //查看今天买了没
            if (redisTemplate.hasKey(Constants.REDIS_KEY_TODAY_BUY + userId + ":" + bmsPlatformGood.getId())) {
                orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_TODAY_BUY));
                return orderCommitHolder;
            }
        }
        //一天最多买多少件
        if (bmsPlatformGood.getLimitSellOnce() != Constants.COMMON_FLAG_FALSE_INT) {
            if (num > bmsPlatformGood.getLimitSellOnce()) {
                orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_BUY_LIMIT));
                return orderCommitHolder;
            }
        }
        //总共可购买多少件
        if (bmsPlatformGood.getLimitSell() != Constants.COMMON_FLAG_FALSE_INT) {
            String limitRedisKey = Constants.REDIS_KEY_PLATFORM_ALREADY_BUY;
            String sameUserBuyKey = limitRedisKey + ":user:" + userId;
            boolean lockResult = RedisTemplateUtils.addLockCanWait(sameUserBuyKey,uuid,2);
            if(!lockResult){
                orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(ActivityEnums.SYS_DELAY));
                return orderCommitHolder;
            }
            paramsMap.put("userBuyGoodLock",sameUserBuyKey + "&" + uuid);
            Double alBuy = null;
            if(redisTemplate.hasKey(limitRedisKey)) {
                alBuy = redisTemplate.opsForZSet().score(limitRedisKey, "user:" + userId);
            }else {
                alBuy = bmsDxOrderService.findUserBuyMaskNum(userId);
            }
            if (alBuy != null) {
                Integer alreadyBuyNum = alBuy.intValue() + num;
                if (alreadyBuyNum > bmsPlatformGood.getLimitSell()) {
                    orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_BUY_MAX));
                    return orderCommitHolder;
                }
            }
        }
        Integer count = 0;
        Integer updateRow;
        boolean isCanGet = false;
        while (true) {
            //非阻塞
            updateRow = bmsPlatformGoodService.updateInventoryNum(bmsPlatformGood.getId(), num, bmsPlatformGood.getVersion());
            if (updateRow == 1) {
                isCanGet = true;
                break;
            }
            entityManager.unwrap(Session.class).evict(bmsPlatformGood);
            bmsPlatformGood = bmsPlatformGoodService.findById(bmsPlatformGood.getId());
            //每次不成功都会判断
            if (bmsPlatformGood.getInventory() <= 0) {
                orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.CODE_PLATFORM_GOOD_SELL_FIN));
                return orderCommitHolder;
            }
            if (bmsPlatformGood.getInventory() < num) {
                orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(PlatformGoodEnum.PLATFORM_GOOD_INV_NO));
                return orderCommitHolder;
            }
            if (count >= 100) {
                break;
            }
            count++;
        }
        if (!isCanGet) {
            orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.result(ActivityEnums.SYS_DELAY));
            return orderCommitHolder;
        }
        String redisKey = Constants.REDIS_KEY_PLATFORM_GOOD_IN;
        redisTemplate.opsForZSet().incrementScore(redisKey, uuid + ":" + goodId, num);
        orderCommitHolder.getUserData().put("platformNumRedisKey", uuid);
        Double totalConsum = ArithUtil.mul(num, bmsPlatformGood.getGoodPrice());
        if (buyArea == BmsPlatformGoodService.MASK_ID_OUT) {
            totalConsum = ArithUtil.mul(num, bmsPlatformGood.getGoodPriceOut());
        }
        Double actualConsum = totalConsum;
        bmsDxOrder.setPlatformBuyNum(num);
        bmsDxOrder.setPlatformGoodId(bmsPlatformGood.getId());
        bmsDxOrder.setTotalConsum(totalConsum);
        bmsDxOrder.setActualConsum(actualConsum);
        Map<String, Object> shopList = new HashMap<>();
        shopList.put("address", address);
        shopList.put("contact",contact);
        shopList.put("contactPhone",contactPhone);
        bmsDxOrder.setShopList(JSON.toJSONString(shopList));
        orderCommitHolder.getExecutionResult().putAll(ResultMapHelper.success());
        return orderCommitHolder;
    }
}
